package net.butfly.bus.server.router;

import java.util.HashMap;
import java.util.Map;

import net.butfly.bus.TX;
import net.butfly.bus.config.Config;
import net.butfly.bus.router.DirectoryPolicy;
import net.butfly.bus.router.Router;
import net.butfly.bus.router.RouterBase;
import net.butfly.bus.router.RoutingPolicy;
import net.butfly.bus.server.config.ServerConfig;
import net.butfly.bus.server.config.bean.RouterBean;

public class DefaultRouter extends RouterBase implements Router {
	public DefaultRouter(Config config) {
		super(config);
	}

	@Override
	public String route(String tx, String version) {
		if (this.routingPolicy != null) {
			String[] nodeIDs = this.directoryPolicy.lookup(tx, version);
			if (nodeIDs != null) {
				return this.routingPolicy.lookup(tx, version, nodeIDs);
			}
		}
		return null;
	}

	@Override
	public String route(String tx) {
		return route(tx, TX.INIT_VERSION);
	}

	private Map<String, DirectoryPolicy> directoryMap = new HashMap<String, DirectoryPolicy>();

	@Override
	protected DirectoryPolicy getDirectoryPolicy() {
		ServerConfig c = (ServerConfig) config;
		RouterBean routerBean = c.getRouterBean();
		DirectoryPolicy directory = directoryMap.get(routerBean.getDirectory());
		if (directory == null) {
			synchronized (directoryMap) {
				if (RouterType.isDirectoryOfSimple(routerBean.getDirectory())) {
					directory = new SimpleDirectory(c);
				}
				if (directory != null) {
					directoryMap.put(routerBean.getDirectory(), directory);
				}
			}
		}
		return directory;
	}

	private Map<String, RoutingPolicy> routingMap = new HashMap<String, RoutingPolicy>();

	@Override
	protected RoutingPolicy getRoutingPolicy() {
		ServerConfig c = (ServerConfig) config;
		RouterBean routerBean = c.getRouterBean();
		RoutingPolicy directory = routingMap.get(routerBean.getPolicy());
		if (directory == null) {
			synchronized (this) {
				if (RouterType.isPolicyOfRandom(routerBean.getPolicy())) {
					directory = new RandomRoutingPolicy();
				}
				if (directory != null) {
					routingMap.put(routerBean.getPolicy(), directory);
				}
			}
		}
		return directory;
	}
}
